/*
 * @(#)AbstractListAction.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.framework.web;


import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.framework.dao.AbstractDAObject;
import com.dcivision.workflow.bean.WorkflowProgress;
import com.dcivision.workflow.core.WorkflowProgressManager;
import com.dcivision.workflow.web.MaintWorkflowRecordForm;

/**
 * <p>Class Name:       AbstractListAction.java    </p>
 * <p>Description:      This is a generic action class, purpose to perform the standard result list  </p>
 * <p>                  process.      </p>
 *
 * @author           Zoe Shum
 * @company          DCIVision Limited
 * @creation date    04/07/2003
 * @version          $Revision: 1.39.2.3 $
 */
public abstract class AbstractListAction extends com.dcivision.framework.web.AbstractAction {

  public static final String RETAIN_FORM_KEY = "retain.form";
  protected static String MESSAGE_RECORDS_DELETED = "common.message.records_deleted";
  protected Log log = LogFactory.getLog(this.getClass().getName());
  protected String m_sListName = null;
  protected String m_sListFunctionName = null;

  /**
   *  Constructor - initiate the global variable.
   *
   *  @param      No parameter needed
   *  @return     No return value
   *  @throws     No exception throws
   */
  public AbstractListAction() {
    super();
  }

  /**
   *  Method setListName() - set the name of global list variable.
   *
   *  @param      listName              The name of global list variable
   *  @return     No return value
   *  @throws     No exception throws
   */
  public void setListName(String listName) {
    this.m_sListName = listName;
  }

  /**
   *  Method getListName() - get the name of global list variable.
   *
   *  @return     The name of global list variable
   */
  public String getListName() {
    return(this.m_sListName);
  }

  /**
   *  Method setListName() - set the name of global list variable.
   *
   *  @param      listFunctionName      The name of global list function variable
   *  @return     No return value
   *  @throws     No exception throws
   */
  public void setListFunctionName(String listFunctionName) {
    this.m_sListFunctionName = listFunctionName;
  }

  /**
   *  Method getListName() - get the name of global list variable.
   *
   *  @return     The name of global list function variable
   *  @throws     No exception throws
   */
  public String getListFunctionName() {
    return(this.m_sListFunctionName);
  }

  /**
   *  Method execute() - generaic function of result list handling, including:
   *                     1. Delete record in List
   *                     2. Get List Data
   *
   *  @param      mapping               ActionMapping from struts
   *  @param      form                  ActionForm from struts
   *  @param      request               HttpServletReuqest
   *  @param      respond               HttpServletRespond
   *  @return     ActionForward         Return the action forward object for struts
   *  @throws     ServletException      Throws ServletException
   */
  public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws ServletException {

    AbstractSearchForm searchForm = findExpectForm4ListAction(mapping, (AbstractSearchForm) form, request);
    log.info(this.getClass().getName()+", OP Mode:"+searchForm.getOpMode()+", Nav Mode:"+searchForm.getNavMode());

    // Set the function code for current action.
    ActionForward forward = this.retrieveFunctionCode(request, response, mapping);
    if (forward!=null) {
      return forward;
    }

    if (GlobalConstant.OP_MODE_LIST_DELETE.equals(searchForm.getOpMode())) {
      try {
        this.deleteListData(mapping, searchForm, request, response);
        this.commit(request);
        if (!Utility.isEmpty(searchForm.getBasicSelectedID())){
        	addMessage(request, MESSAGE_RECORDS_DELETED, ""+searchForm.getBasicSelectedID().length);
        }
        searchForm.setBasicSelectedID(null);
        searchForm.setOpMode(null);

        // Check for all item deletes per page
        this.getListData(mapping, searchForm, request, response);
      } catch (ApplicationException e) {
    	
        this.rollback(request);
        /*
         * Update Code Start
         * Author	Jim.Zhou
         * Date		2006/03/29
         */
        request.setAttribute(this.m_sListName, new ArrayList());
        /*
         * Update Code End
         */
      }
    } else {
      try {
        this.getListData(mapping, searchForm, request, response);
      } catch (ApplicationException e) {
        this.handleApplicationException(request, e);
        request.setAttribute(this.m_sListName, new ArrayList());
      }
    }

    List resultList = (List)request.getAttribute(this.m_sListName);
    while ( (resultList.size()==0) && (TextUtility.parseInteger(searchForm.getCurStartRowNo())>TextUtility.parseInteger(searchForm.getPageOffset())) ) {
      int prvRowNo = TextUtility.parseInteger(searchForm.getCurStartRowNo())-TextUtility.parseInteger(searchForm.pageOffset);
      searchForm.setCurStartRowNo(TextUtility.formatInteger(prvRowNo));
      this.getListData(mapping, searchForm, request, response);
    }

    return mapping.findForward(GlobalConstant.NAV_MODE_LIST);
  }

  /**
   *  Method getListData() - retrieve the appropriate item list for current page
   *
   *  @param      mapping               ActionMapping from struts
   *  @param      form                  ActionForm from struts
   *  @param      request               HttpServletReuqest
   *  @param      respond               HttpServletRespond
   *  @return     void
   *  @throws     ApplicationException  Throws Exception if cannot get the list data from DAO object
   */
  public void getListData(ActionMapping mapping, AbstractSearchForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    AbstractDAObject dao = this.getMajorDAObject(request);
    request.setAttribute(GlobalConstant.DAO_KEY, dao);
    List resultList = null;
    if (this.getListFunctionName()==null) {
      resultList = dao.getFullList(form);
//      resultList = null;        
    } else {
      // According to the list function name to call the corresponding function in the DAO.
      try {

        Method mth = dao.getClass().getMethod(this.getListFunctionName(), new Class[] { AbstractSearchForm.class });

        resultList = (List)mth.invoke(dao, new Object[] {form});
      } catch (NoSuchMethodException nsme) {
        log.error("List Method Not Found.", nsme);
      } catch (java.lang.reflect.InvocationTargetException ite) {
        if (ite.getCause() instanceof ApplicationException) {
          throw (ApplicationException)ite.getCause();
        } else {
          throw new ApplicationException(ErrorConstant.COMMON_FATAL_ERROR, ite);
        }
      } catch (Exception e) {
        log.error("Call Function Exception.", e);
      }
    }
    request.setAttribute(this.m_sListName, resultList);
  }

  /**
   *  Method deleteListData() - delete the item(s) from listing page
   *
   *  @param      mapping               ActionMapping from struts
   *  @param      form                  ActionForm from struts
   *  @param      request               HttpServletReuqest
   *  @param      respond               HttpServletRespond
   *  @return     void
   *  @throws     ApplicationException  Throws ApplicationException the deleteion failed
   */
  public void deleteListData(ActionMapping mapping, AbstractSearchForm form, HttpServletRequest request, HttpServletResponse response) throws ApplicationException {
    AbstractDAObject dao = this.getMajorDAObject(request);
    dao.deleteList(form.getBasicSelectedID());
  }
  
  /**
   * According to the opMode, if request original form which is stored in session scope, use it as the expect form,
   * otherwise, return current form as expect form.
   */
  protected AbstractSearchForm findExpectForm4ListAction(ActionMapping mapping, AbstractSearchForm form, HttpServletRequest request) {
    if (form == null) {
      return null;
    }
  
    AbstractSearchForm expectForm = null;
    
    if (GlobalConstant.OP_MODE_LIST_RETAIN.equals(form.getOpMode())) {
      expectForm = (AbstractSearchForm) request.getSession().getAttribute(getRetainFormKey() + RETAIN_FORM_KEY);
    }
    
    if (expectForm != null) {
      request.setAttribute(mapping.getAttribute(), expectForm);
    } else {
      expectForm = form;
    }
    
    request.getSession().setAttribute(getRetainFormKey(), expectForm);
    
    return expectForm;
  }
  
  public String getRetainFormKey() {
    return (getListName() + "." + RETAIN_FORM_KEY);
  }

  public void handleWorkflowRoutine(ActionMapping mapping, AbstractSearchForm form, HttpServletRequest request, HttpServletResponse response, String opMode, String navMode) throws ApplicationException {
    log.debug("Running Workflow ..."+(((WorkflowActionFormInterface)form).getSubmitSystemWorkflow()));
    // Special Handling for Workflow.
    if (form instanceof WorkflowActionFormInterface && this instanceof WorkflowActionInterface && GlobalConstant.TRUE.equals(((WorkflowActionFormInterface)form).getSubmitSystemWorkflow())) {
      WorkflowActionFormInterface wfaForm = (WorkflowActionFormInterface)form;

      // Start workflow track.
      List workflowRecordList = form.getWfRecordList();
      if (!Utility.isEmpty(workflowRecordList)){
        log.debug("Running Workflow ...");
        WorkflowProgressManager wfProgressManager = new WorkflowProgressManager(this.getSessionContainer(request), this.getConnection(request));
        for (int i=0; i<workflowRecordList.size(); i++){
          MaintWorkflowRecordForm recordForm = (MaintWorkflowRecordForm)workflowRecordList.get(i);

          WorkflowProgress progress = (WorkflowProgress)wfProgressManager.startWorkflowTrack(recordForm);
          if (progress!=null){
            request.setAttribute("WF_PROGRESS", progress);
            ((WorkflowActionInterface)this).executeWorkflowRoutine(mapping, wfaForm, request, response, opMode, navMode);
            //bill add for EIP-1500
            this.addMessage(request, "workflow.label.workflow_submission_suffix",progress.getTrackID());
          }
        }
      }
    }
  }
}

